package profile;

import ij.ImagePlus;
import ij.process.ImageProcessor;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;

/**
 * This class represents a symmetry profile.  A symmetry profile is created by
 * finding the center point (c), and then subtracting c-1 from c+1, c-2 from c+2, 
 * and so on until we have a new profile that goes from 0 to c-1
 * 
 * @author cshanes
 */
public class SymmetryProfile extends Profile {
    
    public SymmetryProfile(ImagePlus img, Rectangle r, BufferedImage bimg) {
        super(img, r, bimg);
        doSymmetryConversion();
    }

    /**
     * Symmetry profile takes in an original, full profile and then
     * does the symmetry conversion
     * 
     * @param arr
     */
    public SymmetryProfile(ImagePlus img, double[] arr, BufferedImage imageWithSelection) {
        super(arr);
        this.img = img;
        this.imageWithSelection = imageWithSelection;
        doSymmetryConversion();
    }
    
    /**
     * This constructor should only be called from a unit test
     * 
     * @param arr
     */
    protected SymmetryProfile(double[] arr) {
        super(arr);
        doSymmetryConversion();
    }

    /**
     * This takes the original data and converts it into a symmetry profile.  
     */
    private void doSymmetryConversion() {
        double[] result = new double[arr.length/2];
        int center = arr.length/2 - 1;
        int diff = 1;
        //if the array is odd length, 
        if (arr.length % 2 != 0) {
            diff = 2;
        }
        
        for (int i = 0; i < arr.length/2; i++) {
            //always subtract the larger number from the smaller one so
            //differences always appear as "dips" rather than peaks
            double a = arr[center - i];
            double b = arr[center + (i+diff)];
            result[i] = (a < b) ? (a - b) : (b - a);
        }
        
        arr = result;
        cropInfo = new CropInfo(0, arr.length);
    }
    
    /**
     * SymmetryProfile has to override performLowPassFilter because it doesn't work
     * with negative values.  To get around this, we simply convert the values
     * to positive before performing the blur, then back to negative when we
     * put them back in the profile
     */
    @Override
    protected void performLowPassFilter(int x, int width, double radius) {
        //before doing the filter, make a "backup" of the original so we can reset
        //to the original if the user wants to
        if (originalArr == null) {
            originalArr = new double[arr.length];
            System.arraycopy(arr, 0, originalArr, 0, arr.length);
        }
        
        int height = 10;
        ImageProcessor ip = createImageForFilter(width, height);

        
        int[] rangeSelected = getRange(x, width);
        //make the values positive before putting them in the ImageProcessor
        //so the blur will work correctly
        for (int i = 0; i < rangeSelected.length; i++) {
            rangeSelected[i] *= -1;
        }
        
        for(int i = 0; i < height; i++) {
            ip.putRow(0, i, rangeSelected, width);
        }
        
        doGaussianBlur(ip, radius);
        
        //put filtered values back into profile
        int[] result = new int[width];
        //using the 5th row here, but we could use any row
        ip.getRow(0, 5, result, width);
        
        //now flip the values back to negative
        for (int i = 0; i < result.length; i++) {
            result[i] *= -1;
        }
        setArray(result, x, width);
    }
    
    @Override
    public String getYAxisLabel() {
        return "Pixel value difference"; 
     }
    
    @Override
    public String getSuggestedFilename() {
        String suggestedFilename = super.getSuggestedFilename();
        suggestedFilename += "_symmetry";
        return suggestedFilename;
    }

}
